package org.ranshiyan.utils;

import cn.hutool.crypto.SecureUtil;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.encoders.Hex;

import java.io.UnsupportedEncodingException;
import java.security.Security;
import java.util.Arrays;

/**
 * sm3加密算法工具类
 */
public class Sm3Utils {
    private static final String ENCODING = "UTF-8";
    static {
        Security.addProvider(new BouncyCastleProvider());
    }


    /*
    sm3算法加密
     */
    public static String generateSM3HASH(String src) {
        byte[] md = new byte[32];
        byte[] msg1 = src.getBytes();
        SM3Digest sm3 = new SM3Digest();
        sm3.update(msg1, 0, msg1.length);
        sm3.doFinal(md, 0);
        String s = new String(Hex.encode(md));
        return s.toUpperCase();
    }

    /** 
    * @Author: zkpeng
    * @Description: sm3算法加密 
    * @Param: [paramStr] 待加密字符串
    * @return: java.lang.String 返回加密后，固定长度=32的16进制字符串
    * @Date: 2020/5/6 11:01
    */
    public static String encrypt(String paramStr) {
        //将返回的hash值转换成16进制字符串
        String resultHexString = "";
        try {
            //将字符串转换成byte数组
            byte[] srcData = paramStr.getBytes(ENCODING);
            //调用hash()
            byte[] resultHash = hash(srcData);
            //将返回的hash值转换成16进制字符串
            resultHexString = ByteUtils.toHexString(resultHash);
        } catch (UnsupportedEncodingException e) {
            System.out.println(e.getMessage());
        }
        return resultHexString;
    }

    /**
    * @Author: zkpeng
    * @Description:  生成对应的hash值
    * @Param: [srcData] 
    * @return: byte[] 返回长度=32的byte数组
    * @Date: 2020/5/6 11:08
    */
    public static byte[] hash(byte[] srcData) {
        SM3Digest digest = new SM3Digest();
        digest.update(srcData, 0, srcData.length);
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash, 0);
        return hash;
    }

    /** 
    * @Author: zkpeng
    * @Description: 判断源数据与加密数据是否一致，通过验证源数据与生成的hash数组是否为同一数组，验证2者是否是同一数据
    * @Param: [srcStr, sm3HexString] 源字符串，16进制字符串
    * @return: boolean 校验结果
    * @Date: 2020/5/6 11:16
    */
    public static boolean verify(String srcStr, String sm3HexString) {
        boolean flag = false;
        try {
            byte[] srcData = srcStr.getBytes(ENCODING);
            byte[] sm3Hash = ByteUtils.fromHexString(sm3HexString);
            byte[] newHash = hash(srcData);
            if (Arrays.equals(newHash, sm3Hash))
                flag = true;
        } catch (UnsupportedEncodingException e) {
            System.out.println(e.getMessage());
        }
        return flag;
    }

    public static void main(String[] args) {
        System.out.println(SecureUtil.md5("5H8O0sbAMXqFnl/iQVSM+8528pmHSvJY71y2auxjqKmHWNDrePRWEafdRBorArf8"));
    }
}
